import {GameConfig} from "./GameConfig"

async function loadGLBFromURL(THREE, url) {
  return new Promise((resolve, reject) => {
    // const buffer = wx.getFileSystemManager().readFileSync(url);
    wx.cloud.downloadFile({
      fileID: url,
      success: res=>{
        const tempFilePath = res.tempFilePath
        console.log("Temp file:" + tempFilePath)

        wx.getFileSystemManager().readFile({
          filePath: tempFilePath,
          success(res){
            console.log("Got the file!")
            const loader = new THREE.GLTFLoader();
            loader.parse(res.data, '', (gltf) => {
              console.log("Converted to gltf!") 
              resolve(gltf);
            }, reject);
          },
          fail: reject
        })
      },
      fail: reject
    })
  })
}

const DirectionAngles = {
  0: 180, // 0	Up
  1: 0, // 1	Down
  2: 90, // 2	Left
  3: -90, // 3	Right
  4: 135, // 4	Up Left
  5: -135, // 5 Up Right
  6: 45, // 6	Down Left
  7: -45, // 7	Down Right
  8: 0 // 8	Any
};

function findSceneMesh(root, name) {
  let resMesh = null
  root.traverse(child => {
    if (child.isMesh && child.name == name) {
      resMesh = child
    }
  })
  return resMesh
}

function adjustExtensionAngle(cutDir){
  if(cutDir > 1000){
    let angle = (cutDir - 1000) %360;
    if(angle > 180)
    {
      angle -= 360;
    }
    return -angle;
  }
  return null;
}

let gltfTemplate = null

async function loadGLTFTemplate(THREE){
  if(gltfTemplate == null){
      // 路径为本地文件系统路径（如 wx.downloadFile 后获得的路径，或 wx.getFileSystemManager 访问的本地）
      const loadPromise = loadGLBFromURL(THREE, "cloud://cloud1-5glactmvb0dcbc62.636c-cloud1-5glactmvb0dcbc62-1353975951/Note.glb");
      loadPromise.then((result)=>{
        gltfTemplate = result;
        gltfTemplate.scene.scale.set(0.01, 0.01, 0.01);
        gltfTemplate.scene.rotation.x = Math.PI * 3.0 / 2.0;
      })

      return loadPromise;
    }
}

class Cube {
  THREE
  scene
  material
  mesh
  isAlive = true
  constructor(scene) {
    this.scene = scene
  }

  noteEvent
  setEvent(noteEvent){
    this.noteEvent = noteEvent;
    this.setGrid(noteEvent.LineIndex, noteEvent.LineLayer);
    this.setDirection(noteEvent.CutDirection, noteEvent?.AngleOffset ?? 0)
    this.setType(noteEvent.Type)
  }

  getEvent(){
    return this.noteEvent;
  }

  setAlive(isVisible){
    this.isAlive = isVisible;
    this.mesh.visible = isVisible;
    if(!isVisible){
      this.noteEvent = null;
      this.scene.remove(this.mesh)
    }else{
      this.scene.add(this.mesh)
    }
  }

  setGrid(index, layer){
    this.col = index; // horizontal row 0 - 3. 0 is the left-most lane. This is the vertical column.
    this.row = layer; // vertical column 0 - 2. 0 is the bottom-most lane. This is the horizontal row.

    this.mesh.position.set(
      ...GameConfig.GetGridPositionXY(index, layer), 0.0
    )
  }

  setType(type){
    this.bloq.material = GameConfig.GetSaberMaterial(this.THREE, type)
  }

  // Refer to: https://bsmg.wiki/mapping/map-format/beatmap.html
  setDirection(dir, angleOffset = 0) {
    let angle = adjustExtensionAngle(dir)
    if(!angle){
      angle = DirectionAngles[dir]; // Why angleOffset is wrong??? + angleOffset;
    }
    if(dir == 8){
      this.dot.visible = true;
      this.arrow.visible = false;
    }else{
      this.dot.visible = false;
      this.arrow.visible = true;
    }

    this.mesh.rotation.y = Math.PI * angle / 180;
  }

  bloq
  arrow
  dot
  init(THREE, color) {
    this.THREE = THREE;
    if(gltfTemplate == null){
      console.error("gltf model not loaded!")
      return;
    }

    // Find meshes
    this.mesh = gltfTemplate.scene.clone(true)
    this.bloq = findSceneMesh(this.mesh, 'Bloq');
    this.arrow = findSceneMesh(this.mesh, 'Arrow');
    this.dot = findSceneMesh(this.mesh, 'Dot')

    this.dot.visible = false;

    this.bloq.material = GameConfig.GetSaberMaterial(THREE, 0);    
    this.mesh.visible = false;
    this.scene.add(this.mesh)
  }

  update(){
    if(this.isAlive){

    }
  }

  getMesh() {
    return this.mesh
  }
}

export {
  Cube,
  loadGLTFTemplate
}